//
//  SystemCalendarEvent.m
//  AccessSystemCalendar
//
//  Created by Felix Yin on 2017/3/20.
//  Copyright © 2017年 Felix Yin. All rights reserved.
//

#import "SystemCalendarEvent.h"
#import <EventKit/EventKit.h>
#import "CalendarEventModel.h"
#import "CalendarEventViewModel.h"

@implementation SystemCalendarEvent


#pragma mark Initional Object

- (instancetype)init{
    self = [super init];
    [self initionalCaleventStore];
    return self;
}

+ (instancetype)shareSystemCalendarEvent{
    
    static SystemCalendarEvent *systemEvent = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        systemEvent = [[SystemCalendarEvent alloc] init];
    });
    return systemEvent;
}


- (void) initionalCaleventStore{
    [self.eventStrore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError * _Nullable error) {
        if(granted){
            NSLog(@"😄😄😄😄允许访问 日历事件");
        }else{
            NSLog(@"😭😭😭😭不允许访问 日历事件");
        }
    }];
}


#pragma mark Operation Module

- (void) getSystemCalendarEvent{
    NSLog(@"允许访问 日历事件");
    NSDate *startDate = [NSDate date];
    
    NSDate *endDate = [[NSDate date] dateByAddingTimeInterval:24 * 60 * 60 * 365];
    NSArray *tempA = [self.eventStrore calendarsForEntityType:EKEntityTypeEvent];
    NSMutableArray *typeArray = [[NSMutableArray alloc] init];
    
    for (int i = 0; i < tempA.count; i++) {
        EKCalendar *tempCalendar = tempA[i];
        EKCalendarType type = tempCalendar.type;
        if(type == EKCalendarTypeLocal || type == EKCalendarTypeCalDAV){
            [typeArray addObject:tempCalendar];
        }
    }
    
    NSPredicate *predicate = [self.eventStrore predicateForEventsWithStartDate:startDate endDate:endDate calendars:typeArray];
    NSArray *events = [self.eventStrore eventsMatchingPredicate:predicate];
    events = [events sortedArrayUsingSelector:@selector(compareStartDateWithEvent:)];
    NSMutableArray *eventViewModels = [[NSMutableArray alloc] init];
    
    for (EKEvent *e in events) {
        CalendarEventModel *eventModel = [[CalendarEventModel alloc] init];
        EKRecurrenceRule *rule = [e.recurrenceRules firstObject];
        //                EKRecurrenceFrequencyDaily       0
        //                EKRecurrenceFrequencyWeekly   1
        //                EKRecurrenceFrequencyMonthly  2
        //                EKRecurrenceFrequencyYearly     3
        NSLog(@"Inteval  ==== > %@       =======> %li",@(rule.interval),rule.frequency);
        
        eventModel.eventID = e.eventIdentifier;
        eventModel.eventTitle = e.title;
        eventModel.eventStartDate = e.startDate;
        eventModel.eventEndDate = e.endDate;
        eventModel.eventNotes = e.notes;
        CalendarEventViewModel *eventViewModel = [[CalendarEventViewModel alloc] initWithModel:eventModel];
        [eventViewModels addObject:eventViewModel];
    }
    if([self.delegate respondsToSelector:@selector(systemCalendarEvent:events:)]){
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.delegate systemCalendarEvent:self events:eventViewModels];
        });
    }

}


- (void) saveEventToSystemCalendar:(NSArray *)array{
    if(!_eventStrore){
        return;
    }
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        for (CalendarEventViewModel *viewModel in array) {
            [weakSelf saveSingleEvent:viewModel];
        }
    });
}


- (void) removeEvent:(NSString *) eventID{
   __block  NSError *err = nil;
    NSString *ID = [[NSUserDefaults standardUserDefaults] objectForKey:eventID];
    EKEvent *e = [self getSingleEvent:ID];
    if(!e || !_eventStrore){
        return;
    }
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [weakSelf.eventStrore removeEvent:e span:EKSpanThisEvent error:&err];
    });
}


- (void)modifyEvent:(NSArray *)array{
    
    if(!_eventStrore){
        return;
    }
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        for (CalendarEventViewModel *viewModel in array) {
            [self  modifySingleEvent:viewModel];
        }
    });
    
}


+ (BOOL)isAccessSystemCalendar{
    EKAuthorizationStatus status =   [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
    return (status == EKAuthorizationStatusAuthorized) ? YES : NO;
}


#pragma mark Logic Handle

- (EKEvent *) getSingleEvent:(NSString *)eventID{
    if(eventID.length < 1){
        return nil;
    }
   EKEvent *e = [self.eventStrore eventWithIdentifier:eventID];
    return e;
}


- (void) modifySingleEvent:(CalendarEventViewModel *) viewModel{
    
        NSString *eventID = [[NSUserDefaults standardUserDefaults] objectForKey:viewModel.eventID];
        EKEvent *e = [self getSingleEvent:eventID];
        if (!e) {
            [self saveSingleEvent:viewModel]; //当换一部手机，修改行程时
            return;
        }
        e.location = viewModel.locationStr;
        e.notes = viewModel.eventNotes;
    
        NSDate *startDate = [self dateFormateFromDateStr:viewModel.eventStartDate];
        e.startDate = startDate;
        e.endDate = viewModel.eventEndDate.length > 0 ?  [self dateFormateFromDateStr:viewModel.eventEndDate] : startDate;
    
//        NSLog(@"(Modify)start event id === > %@",e.eventIdentifier);
    
        EKAlarm *alarm = [e.alarms lastObject];
        [e removeAlarm:alarm];
        NSInteger timeInterVal = [viewModel.alarmTime integerValue];
        [e addAlarm:[EKAlarm alarmWithRelativeOffset:timeInterVal]];
        [e setCalendar:[self.eventStrore defaultCalendarForNewEvents]];
        
        NSError *err = nil;
        [self.eventStrore saveEvent:e span:EKSpanThisEvent error:&err];
    
//        NSLog(@"(Modify)end event id === > %@",e.eventIdentifier);
}


- (void) saveSingleEvent:(CalendarEventViewModel *) viewModel{
    
        EKEvent *event = [EKEvent eventWithEventStore:self.eventStrore];
        event.title = @"碰碰日程";
        event.location = viewModel.locationStr;
        event.notes = viewModel.eventNotes;
        
        NSDate *startDate = [self dateFormateFromDateStr:viewModel.eventStartDate];
        event.startDate =  startDate;//开始时间
        event.endDate = viewModel.eventEndDate.length > 0 ? [self dateFormateFromDateStr:viewModel.eventEndDate] : startDate;//结束时间
        
        NSInteger timeInterVal = [viewModel.alarmTime integerValue];
        [event addAlarm:[EKAlarm alarmWithRelativeOffset:timeInterVal]]; //提醒时间
        [event setCalendar:[self.eventStrore defaultCalendarForNewEvents]];
        NSError *err;
        [self.eventStrore saveEvent:event span:EKSpanThisEvent error:&err];
    
        //将ID写入到本地
        [[NSUserDefaults standardUserDefaults] setObject:event.eventIdentifier forKey:viewModel.eventID];
    
        NSLog(@"event id === > %@",event.eventIdentifier);
    
}


- (EKEventStore *)eventStrore{
    if(!_eventStrore){
        _eventStrore = [[EKEventStore alloc] init];
    }
    return _eventStrore;
}


#pragma mark Tool Class

- (NSDate *) dateFormatForChina:(NSDate *)date{
    //通过 date 转换到 dateStr
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    NSTimeZone *timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT+0800"];
    [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
    [formatter setTimeZone:timeZone];
    
    NSString *dateStr = [formatter stringFromDate:date];
    //通过 dateStr 转换到 date
    NSDateFormatter *formatter2 = [[NSDateFormatter alloc] init];
    [formatter2 setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
    NSTimeZone *timeZone2 = [NSTimeZone timeZoneForSecondsFromGMT:8];
    [formatter2 setTimeZone:timeZone2];
    
    NSDate *d = [formatter2 dateFromString:dateStr];
    
    return d;
}

/**
 *  将GMT+8时间转化为 UTC+
 *
 *  @param dateStr 时间字符串
 *
 *  @return 返回转换后的时间
 */
- (NSDate *) dateFormateFromDateStr:(NSString *) dateStr{
    //通过 dateStr 转换到 date
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    
    NSString *formatterStr = @"YYYY-MM-dd HH:mm:ss";
    if(dateStr.length == 10){
        formatterStr = @"YYYY-MM-dd";
    }
    [formatter setDateFormat:formatterStr];
    NSDate *d = [formatter dateFromString:dateStr];
    return d;
}


@end
